// evmone: Fast Ethereum Virtual Machine implementation
// Copyright 2024 The evmone Authors.
// SPDX-License-Identifier: Apache-2.0

#include "../utils/utils.hpp"
#include <benchmark/benchmark.h>
#include <intx/intx.hpp>
#include <state/precompiles.hpp>
#include <state/precompiles_internal.hpp>
#include <array>
#include <memory>
#include <span>

#ifdef EVMONE_PRECOMPILES_GMP
#include <state/precompiles_gmp.hpp>
#endif

#ifdef EVMONE_PRECOMPILES_SILKPRE
#include <state/precompiles_silkpre.hpp>
#endif

namespace
{
using namespace evmone::state;
using namespace evmone::test;

using ExecuteFn = ExecutionResult(
    const uint8_t* input, size_t input_size, uint8_t* output, size_t output_size) noexcept;

template <PrecompileId>
constexpr auto analyze = 0;
template <>
constexpr auto analyze<PrecompileId::identity> = identity_analyze;
template <>
constexpr auto analyze<PrecompileId::ecrecover> = ecrecover_analyze;
template <>
constexpr auto analyze<PrecompileId::expmod> = expmod_analyze;
template <>
constexpr auto analyze<PrecompileId::ecadd> = ecadd_analyze;
template <>
constexpr auto analyze<PrecompileId::ecmul> = ecmul_analyze;
template <>
constexpr auto analyze<PrecompileId::ecpairing> = ecpairing_analyze;
template <>
constexpr auto analyze<PrecompileId::point_evaluation> = point_evaluation_analyze;
template <>
constexpr auto analyze<PrecompileId::p256verify> = p256verify_analyze;

template <PrecompileId>
const inline std::array inputs{0};

template <>
const inline std::array inputs<PrecompileId::identity>{
    bytes(4096, 0),
    bytes(4096, 1),
};

template <>
const inline std::array inputs<PrecompileId::ecrecover>{
    "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c"
    "000000000000000000000000000000000000000000000000000000000000001c"
    "73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f"
    "eeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549"_hex,

    // Inputs from https://etherscan.io/block/19570693
    "e6a825e35ed9be084a71892d40a03353bcc64daf121816aebb219e3a1adadee3000000000000000000000000000000000000000000000000000000000000001c16799fd127010cc658053f838ba1dbcf49274fe97d14da1c08456c917d303ad4495b97615ae683e5677714e1aa5470d2d5e95f50781cee24d12e5972b853a4be"_hex,
    "e37c09431f6725ecb8de43e77fa48a598d6dcaee19dbdd0782a56bb5d8d76f1b000000000000000000000000000000000000000000000000000000000000001cd1507bb892a41f02648e61ab306c7acc7efc50669bab3bbb179e4f21386cab5a72c3f4b47f12b7a42dec6e220792b8b7f7c2aefa9e57869d165be54061d38d37"_hex,
    "06cfd18cbba471f873110ce951f8709243ad4ee3963c0f37ca748fd8f4cb277d000000000000000000000000000000000000000000000000000000000000001c5e4a4eafc75a38761f986807a7c3c3ce3dc6d8d1b54e77e0d8f61550cb145f5609d82baa98f5affc6c1fa92da7df6bfd957c23dbaa80c43069ddd31de4b06b50"_hex,
    "ad11ccc6f37519a248f72617eb6895db5227816ecc02ffb04d7f3ead7c68c9c5000000000000000000000000000000000000000000000000000000000000001cbec7fc01246483c331848dca2435ef566c405f49c80773ed1e37c7d8e5f9763c014f06796c5f2eb28799a7d1b933e420e0a8179a7f041f7b177bb749887e3fdb"_hex,
    "845f0b1cab4c6780c61f88cd8018646af7d92f513b8478290ad607ec2c81699b000000000000000000000000000000000000000000000000000000000000001c190b2d1d6152613f92fa9406825206ea21290e4cf61e5729098d35fdf5779d4d4e008b79b927f35879c4a05444113857b0073bf336dfa0ed647809599e6f682d"_hex,
    "09b985f366a070978c1871df5d78cf890c8a51417c5a4aeaf6019a25bc6478be000000000000000000000000000000000000000000000000000000000000001bb6d464798c025aacffd1a56e0643a1ac29f6ed62f282c2e5b13bc0bbec08647c299cfa2e7c295fa7387856eedb34a94a30728fe96f6caf3c5e02c6ce0467ec3f"_hex,
    "9d160608ad1a2d3c0f9ee91b566a0f63cdd6297b255b7860485dc80915b6edd1000000000000000000000000000000000000000000000000000000000000001cab06c8d09cc508cd173b7c1943fe76b307dfd1472eac56455ad820a17b7748f87874cb1337d734eb8497f7c5b2ae78289a8806f636382140872ba414ba7b2cef"_hex,
    "c866f7d081b5ed51c07478c05950c6d49b57f9dc7e9517f2a49235dffad87ff9000000000000000000000000000000000000000000000000000000000000001b8ac1b5ea65ca74923e5d55a36649775fd4a6383a43625ebe72e80cffab2e73cc71fe84fa6b92785ccf0cb47703f6978d02199027c893e2e578d4a3b756f8a60b"_hex,
    "c866f7d081b5ed51c07478c05950c6d49b57f9dc7e9517f2a49235dffad87ff9000000000000000000000000000000000000000000000000000000000000001cf584733b44d6a4997ffb9cd2c55ad194fa105f99fb9a02265c4b02a1ab987ea93c83271a5023cda2d536fcb57676a4029c62fab694d6defd997939d0eb738ca8"_hex,

};

template <>
const inline std::array inputs<PrecompileId::expmod>{
    // Worst cases:
    "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000020ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"_hex,
    "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000020ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"_hex,
    "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"_hex,

    // Mainnet:
    "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000203038f57abc91abff7dcbc5b55cd6aa454503850ce62e941f81273ba6008e82a530644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"_hex,
    "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020239ea33f993130afd678f591cd1685d44779b7717156f2a715220955e10a234830644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"_hex,
    "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000203914aeddf3af39bd5e0e231d09a8438cf38c7d0274a5aa61bd9a2bbcd77fd2c7ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"_hex,
    "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002027c816cec3d048eaae22d948c42f9d803d765d0827a7b49e01273031566eed92ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"_hex,
    "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200cf7d1e109b5b8f6a682be51e152d3668acc1b4d762ecbf5cdca7a807cc5fe4cffffffff00000001000000000000000000000000fffffffffffffffffffffffdffffffff00000001000000000000000000000000ffffffffffffffffffffffff"_hex,
    "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000203a122fd889a09d3a19c587ab486d5a6a2b39836d6d665c6ebad2a68a615e6736ffffffff00000001000000000000000000000000fffffffffffffffffffffffdffffffff00000001000000000000000000000000ffffffffffffffffffffffff"_hex,
    "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020161455250ee1d7ff76e4eb2f6a16a636a4bc69dd20416f6ea5647b7fb311e9320000000000000000000000000000000000000000000000000000000000ffffff30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"_hex,
    "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200d96428856df2f1b728ce955f28f50befa405a61e8984acbaf678af9be0e0dfd000000000000000000000000000000000000000000000000000000000100000030644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001"_hex,
    "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000202369f74b39dddb516bb17d20f24ba72c8f0ec09bea7d7f38ad54dbc3cfd4b4760c19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f5230644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"_hex,
    "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002019b01e88eb4a62d7df2da453deb859f6113004675370b6f54ff9f20499cfc4cf0c19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f5230644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47"_hex,
    "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020c943d0f2b95b88d8a3ad7782221659f05cb697047a9793a65ec7db59439afb0a3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0cfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"_hex,
    "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020307c38188f3b804fc399b7195579269fd60fddbe7e6d8174b3ad38b64b1bb2fa3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0cfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f"_hex,
};

template <>
const inline std::array inputs<PrecompileId::ecadd>{
    "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2"
    "16da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba"
    "1de49a4b0233273bba8146af82042d004f2085ec982397db0d97da17204cc286"
    "0217327ffc463919bef80cc166d09c6172639d8589799928761bcd9f22c903d4"_hex,

    // Inputs from
    // https://etherscan.io/tx/0xf1d290f8a30e84953e40f32b442f4af4d947ddc88cb9e66f1e551f82d8479e2d
    "2aee4c4a210fe1d6dd0c58e82fa8a8ebb8d6ccd57925d6c719240e7a61aff514232667094a59014c57bf0ad6a220bf66ca1e6ab8b4135fa932bffaba7dc9ac212a2652ced6e8fbaa735ba18f3851e8ef8ece83b2c7f685516eb1eb66860c82eb02840447bfa6500e7cb5532a37b89dfea32159a2769b1ab23d56a95ccfa76174"_hex,
    "0bd35c81c7113a12eabec37f18750aa99294710f22e57da632212a063f59d27a03cb8a97e16ee905fcb2e8c5a9ae9b97b6a3c20d76ebc46b7949673e1c8f40b507524717221895c6f8c667f0b0f9bba8808c1f5e2b19860619921b5ccd70e4e5032a0a201c3e477d68cddf5e26d95ba03fb6dc7cac53e17e2e8fa39267507e48"_hex,
    "0c359809f64010752fe9cde56bee5c6e98d3b362dad9c6e27983a289d7fdec6a10980910c6c33e2b3558464b76f7ce0626f951382ec370c9d92d2828d856731c1d37ba3d0f2cea2251f41a83abf667100a32c090fb5067d42b447f4559398aef07cf5d8560237e4dd19da27b3b49e5e669823375654845561f2108ef4103a574"_hex,
    "1af3c46848da0a5fbeae786b72e49f604ccd2c119d17cd46e516f6534b6075a906c3525efa7be813d47fd339faf5ff0e99adcc71c56a545681820441a3f4a1b922754034f74195e95a897f3570e0fda11e21a39081683528aab029bbdd6c5e230e0ea7e78b3ffaf0d45b3e6169515109292541acf2db63deecd198231f7819b2"_hex,
    "2d518024c07730b00e5f0252e479062b235759fca26e0460a40cfa4816be56af13a98be139f51ea9c6f1a93877056a7efcf89310f33022922c71263791fc107d16f6c6cd86354c8b06edca713969b8c30c7a93f1215e2c99bd28bc59f8b8186b230807cb63532426c0c2d1e13b0c8bef1da721eabc333888d4c6d6ff1a2e513e"_hex,
    "135b515087f247e764f5ee5af75aa52568e34a5738594175bddd43b6f332beea0d70aa546b5f89b5a626f2c97a616f83e0f29722678afed431f3a4abd589c0b42be33cd0bd8ba0e523bd7dd03706154a9709162024a776ee39cacfbcdcf264b523d77a67e344cde7785449d3350ec89e4fd5eb8aad7178f38d824d6113c594c0"_hex,
    "02548a1e93c0c6f79894c37384b9aa26770f31a675920542b5974b400c88f5dc20b5de975ed6c5d749d3555e490b7f8d2d8465b0f322a2b6a9e0679fde711cc80091961eb0f7f63b9357cfed46c61eddbc9a88fc58958461d911e1c5cb9750940506e465f95fde47460eb8fdd060e8ae89c06f665264657266c8543d7de4d3df"_hex,
    "1b1c30a53bce3f8304f27e460305daa9ee811f9de9ab7aa7f1e69a260d64c0c52e9add32cc1f0266381fe46712fac4f2052f0348d2ff202085540111fd2cd1dd209227f4a682645e784055c717d3f1dfa203f2b26096ac700cfc55082519a999064db2c23bdffe9356ba02520baef6fb898333c5c61cdcf7efc2212ed7cb070a"_hex,
    "15fe6f9e26be9c6851f4dceb593c3c3eddccf67abd05e3cba7e816c184c1650a262e4d9cee7dc9c35dcef7ef71d754179d2d2c8a9870b22201a27fed4c137d9b24ce9cd464b722e82eb266cce2be72a00e9f72eb9ea1936e9094b1ba6848a3792ff2346d6546026fe1be4f94416008247512cae8b110c2e06b58db4cb4355117"_hex,
};

template <>
const inline std::array inputs<PrecompileId::ecmul>{
    "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2"
    "16da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba"
    "183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3e7ea3"_hex,

    // Inputs from
    // https://etherscan.io/tx/0xc51e63b391ffddeddf6a797dec9329d2319cff4358989a0e8c41d58968ed8c3d
    "028f9d01bc0cb29ed29374f2e1317da679c7aafdec345db14fa3cc7b7aef3bfe1e7f063cfe3939fe829c6305471a7ecee3a1d414fd1564da6a2435fe7a40dd1f102e3dc989d704b6e15d937f543b5f434326f676ba42dc38cab2a6b531e63c86"_hex,
    "27c865075b86f234c03f92aca6cdea284c5f74db3631795351602c32ffe35e052ca0622cb684b6d03ad8ce2b33e4b607be11dacdd231d3ab068365782988dfe5102e3dc989d704b6e15d937f543b5f434326f676ba42dc38cab2a6b531e63c86"_hex,
    "115ff91c1ff2ec322468e4b55631506f15e0c911c8cbec4fd60e72245836f44b0db5de38601f262bded24fc593c1d15412eec6c3f7fdd1c691befc70fd89c9d916a872d9b0faa63cfacef41a7b0968954386bf94a3b86794a781b4aaa0d296d9"_hex,
    "00b8b470c37deeeab63eed4d8374c4bf000a0be91319a4bb144a87a80732bda904ea9ca099d607fcb70678ac3243175c455abe00ac40a2a2c0cd7ee67b2d946315816eec3322d435e2924f2e87c4a68aa13b79aab0fde90a91bbfb736459f896"_hex,
    "000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020fc9202d44e2bf33f6b4a67e111504852a3a7bf361194f69afa319f8423d703f"_hex,
    "0e4fdac80cf8f87fe27488e0a398e94aaafb93f41d3623c66e10dc306f9ff3a60135a67a4dfb05a35b766b3bbca81b3afe06e823859d52c29f7203615b565c5b17d6661525677e78137f0e34bdbbeec136c1d64642493e6e2825f4d8970e98a2"_hex,
    "00c8a00b8ce94341d4ebf9abe08b5c87ea4d84dc04138a24ceefe0b9c78c4d95067172bf6abf504bbfd5652d643725e79306075513bf5161c3d64b9465964598286e7ccbf31089e0df224914b92a9a0792e323b1f55684c1aa9f7646a62fb3f2"_hex,
    "2d56bbb88255cf631060fa06f154fde7bae56510d6caaec5a0bbc22f252d7aca21e9f7e4584b24a4f105b81de76887052deed89fdce114e161d7e7178213ca0b1d102fb0fde27c3d513d530d25a84ec81d410f89c54c3d66ba4689940ce91dea"_hex,
    "30543adffffd27f2c512df127e6bbf0463986e439ba55bbd668ca5ae649c3de71525e19d26d342eaa4201d3311cbea20aea70c6293823d58f69bc154a672dd7a18089d4e577b2312bc6b0fdf414b55a27f85eda857c40ccbf6aee4eda308b6ee"_hex,
};

template <>
const inline std::array inputs<PrecompileId::ecpairing>{
    "07ef2650307493a16aca9e26a19d6743fff6625c3d8e54d72066927275b5f1eb0e1c313e3efebda72ff799f0290c8da3ddde69186bd55847394e2aad3c0116410055091d6ff0c5409deb107db7771636f49a4f35b8fd67b521529cf750bfd30d25bbf84313e421938a91a38cc2a6ec95231804b8bf4beee4fe918dcff2c62cfb2e7ef6b31b4bed556d3ae77b6bbc156b145d1a8c3589c3d62e3fa3aecb968bb5260c78f7e4f3da71284d1d94afb6f4baed9a897e3713952cd4f94870a43d8ea8"_hex
    "2dbfc3ec62a3eee5a3b4b464bcf1f8527bbca12adea0f1f12033cd4f61b0e09119e55bd0b72c126da18665039556776642ff82e2f347f24fcea2475f4db087df1ae724ab134e5a7c6bd8a116fa5505b259522c0f164a5e8126e3ec7d34465f6e009f1bcdc853f8e3531756bb625b0d1dc014f4ab57c3f79f4f4e2e7ef7e0ead623a8ca5760457e726365b92fd0ceb486665797cd68c35dcffd8e4ae8066691e913ec7182c9fd68331a10f8be0fe885d730de5c7f89aa7d0b7bafaa009bbc9e3e"_hex
    "275d967e24153c39567c2275b998a744042c17fd3c8060df5e32dede307fe6891cafe268593a1b223feb7b3a21f3619ff265e24150adadf917c121b196fce1e1198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa"_hex
    "00f5b874a25a5045aa662c0a73309f53fd80cf68c7d6016b330fea535b3b96e42b454797d9c29e4262de0219926fbee1740553f8282c8c94b3f730d805228d5a2f0c63d0c53b3dfbca27b6b43ae7fbf55a38d78a21470996485b03128accc20800556502356e37ed150db2e36531b0f275fd6835c0fc1945922e270b48c48a8602644c27b5dbd793592a70b735e22c798a5e309fa17a992a7dc2a050e01b298f194776b6a53439d7336f389d2a8f6651e40885f5ca2538b0dc9cb534fb23f7fa"_hex,

    "26466d52f79fd83452765af06723b8261d84292750c79260282c8fbebd32beaf1651abcd90107f0c8f610aac5ad733b6c5e1f726f4de82fdb9320446ec24ed76198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d214a3eaef9e104107226efdf0daa209bbe498dc11dd69a532b84d7d96e519f7e2a5ca5391aef6020d334577a46a7b95b650b048352ee1ffa0e780c4a4b6fe91b21c1193ec74d74e40a1cfa846c34eb49a80a85d000fd4a32910d7e683de704742cc717d69a0a0144d55251b862eb0eb8a208e511ac189673f9774f29d20b5ecd0f1e11d24390d4337b9183c1b5168c086f1bdcc1ab340a3685a7d77a0e7e733608fdd631bb135b5287142da57ec7a6e63adde9ab9750804622fce0af05729e34"_hex,
    "21f61f88c5a038ceb500aa97ef781055a2d54972cdbf57d517096c1abc61bee200668426d1716b4545c1b0c62fc86c963f0cec21e0cd9581f456e63760c68d89198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa260f33258798435df28cf0d2dfbe5f4f4818c58891bdca78d9072319f01aa1cd032d5dea12336387561dd2dd08fb2a2f7c907a43ab53b971002b0ee7d6cba49c186282957db913abd99f91db59fe69922e95040603ef44c0bd7aa3adeef8f5ac17944351223333f260ddc3b4af45191b856689eda9eab5cbcddbbe570ce860d206d971ff4a7467c3ec596ed6efc674572e32fd6f52b721f97e35b0b3d354675306ecdb9f9567f59ed2eee36e1e1d58797fd13cc97fafc2910f5e8a12f202fa9a"_hex,
    "07e7551e3100bff4528b81aac659ca5e4e7170b5e12b8d3e30b9935d3767f48e2ced6ce9c41b8c1acaa3406de772673c367fc348b4b82c7b30da63f10255d3d5198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa0b6512359b04db934f686fbcb6c928f354d1a81ae2252ca5d4aae3896ed8b563288f9675e1e95abf899b49fd15fd0989aa1b690e6d91c29309f55cd78caeffe1260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c10118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b004fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe422febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55"_hex,
    "0dde47c97939443b8ad501c1f9c5f300c8c38b1df716bfcb1710a274950928cb2ef81b076bfe99bf22b96be86ce80533e6888408f8bcc4f80c4a5a4269e745cd0cd0ec776fcd7c8e09c7870d862d38e24a558caf29addc0ddd75b1cf7467b4822e2c6b91e4c6214282f540b93f9a34f4efa6beb19b12ffe3ecc4180ace6d71ed1760fdf5eba14deb33e8388d49ada8b79244bfc6e7955d1eca9034600a5f87572bb0ea13cd218cb83ad685aad55c7044d3dabbff132ba998b8c7b8d33ee31ad001ebed5ab04cf6a52c91c5eeb8115f16d17f65e332972aae330b7f336a12ed5e28cade7e9fe17f6e3b37c95306c0e95601502c5b92c8eaa4b833ca8cb371829c2129813bd7247065ac58eac42c81e874044e199f48c12aa749a9fe6bb6e4bddc1b72b9ab4579283e62445555d5b2921424213d09a776152361c46988b82be8a7111bc8198f932e379b8f9825f01af0f5e5cacbf8bfe274bf674f6eaa6e338e04259f58d438fd6391e158c991e155966218e6a432703a84068a325439657498572d13bbd21d26b18fc8675a11aab05a2db4cc5e67cf6b613e6cca5605b7dbcdc5021fa68be4bf10f345c6d5cfca0d9a7d31d3ed34b6313189e71ebb6eaf78242e198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa2ee53e6ae6469ac25f8a9077a70dc7b2de87b177f37bcaa250bfe0bf1a27c0f41a08736142026f8818c788ed8ab7d3b9095a023ec263885af13c3e9f8f0ee74f0106b9acd3190d55559d315663fd7c9328e349ed9e65609ed04965faa585cc431c440555fec15da4b137a22b124d13d089ed9fbb6255759b86abf9de6e1c761802a73357f1acee0de463c4d3f7535fb23b1317bf6f2ebd078cb7a2e06f882284226254d43204a6add64a6ba65c34c0e6dd13a10888686512efe422afa9608bc6"_hex,
    "22c1231e502334e41aca24dee7d962bd7deb7bf45beefd24baebdc181662032529793c3f9e578f731da72ff7e77c3e4aa596bc70f2f18efe861e09d80063055708a802562853078a00073b1a56bdce6974d49999ffe8e57b090fcf50470ee3241867b1193c349d4178fd38349e5dcacbf7fa5169d207d9dc359b2e099047dfd0250d4a0c29531021d3108e1a4851c42ead8697fd2d964db2896afd65039a5a59059fdbd52731e25f6f035686022edc867603dc01503bbcf3e44ffd0263666d552d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d19260967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec8099c1293f4a7d755cc5895151912cfd89a6114493298ad4559295ac2c0219bc801505f18b3779a8cf3b4cbd4b3c0dbd99ab2c6e3e825e6e3e3bd56ff6961f117198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa0d39a10a81e9e8cd251f6c18b9d8c7a2b4ba3f9506c8001638b1bd4c663ca82b172e3638278ba81d883a0e486d597b3a50f9d9e026cf8bd5e940bf031f1bbbda2c4e22719c67bf7bddedcc98face8265be63ccdcef8139c221f21326aa48d1bd0700cbe071c394f095926c90427fe8a412216739e7633acb7c02cd719c12ecb92b34f9525b49f109aed50c68544acf38750b4c7334709d328de3973744953fcb0923b1a411590566dc946db78f12e46e568b91150d4b929ff7b4b5aba0fbab7b"_hex,
    "2b8246fa78c0cdbc5a9b6e3ae245229769e3727bede3510aa5391e222c1a16782463d5b720d0b501b1cb00a30faa508b220acdde498c03838897bf98f1348457198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa1613ee9c617b7e7858928a236adc00a4200a7695a010e142d00966651587f516262f5022362a6547c3a991c74ad56caea45b80d5796eb0668fcf72983d170af0260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c10118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b004fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe422febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55"_hex,
    "000aa497c1b40b6f07989a7cca77c3e53dee08632433a90955d0c82f3a445937191c2f6a70d2cdd33e65907a67ebd0520e8394506e64cc43d805a3fd483e56990c0e8dc0367bcba1ec70160c11c981cd60432322c946a0a141cf7955e445e95506c1bcaeed380b606a7c05b696be5264dcb4da87342e6788c7adc536c121720d0bb73da5d6e75c353e3273c9a4196240d83f255f18af276c1ab2f5bff77f0ebb0f7cb99dc5db1aec72f855fc4fc1c6e9c0620405c8ff1343ff958a36cd2c05b301ebed5ab04cf6a52c91c5eeb8115f16d17f65e332972aae330b7f336a12ed5e28cade7e9fe17f6e3b37c95306c0e95601502c5b92c8eaa4b833ca8cb371829c2129813bd7247065ac58eac42c81e874044e199f48c12aa749a9fe6bb6e4bddc1b72b9ab4579283e62445555d5b2921424213d09a776152361c46988b82be8a7111bc8198f932e379b8f9825f01af0f5e5cacbf8bfe274bf674f6eaa6e338e04259f58d438fd6391e158c991e155966218e6a432703a84068a325439657498570ca8a4e8513506772cd613017c98f5d22bef7e6f0f11b020c69a11c42402ae1f0ea63a9620ea5f23af6814584b4839f4b5bc9bc444d6e3a45fdd314f33b5e47d198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa0228e296bbd09b1ab50534a35e2572c874ed6bc2d743d964c35d1ee6e07c5e91119dbba8ead4ff7f04b9824016551efaa4eafdd2d599ab029149d80bb28eb2b50106b9acd3190d55559d315663fd7c9328e349ed9e65609ed04965faa585cc431c440555fec15da4b137a22b124d13d089ed9fbb6255759b86abf9de6e1c761802a73357f1acee0de463c4d3f7535fb23b1317bf6f2ebd078cb7a2e06f882284226254d43204a6add64a6ba65c34c0e6dd13a10888686512efe422afa9608bc6"_hex,
    "08b36935645d3cf03da1a44e1c500220e192bc25d7c2258b0e0162daa4cb51ce12fa21e6b7c12050ae82728acf6ffc0d223bee2cd2fed72a8e666531ccd1ed7e01ef8a2f7b663d2929b81e5fddded62747fdb102360f83e268eaf61524bb9e6f0870d564fb18fadd334959b16b916f9cac89685972d38b991147913daa2ff4d609cb2d1f22a263b144f56f84b5ca7fc3b0cad00246e0fb824f8f4d364e4501c423758d28bc118dd4899d126d7eeb041bf255cdccd7052a7af68f6ce2911a22ca01ebed5ab04cf6a52c91c5eeb8115f16d17f65e332972aae330b7f336a12ed5e28cade7e9fe17f6e3b37c95306c0e95601502c5b92c8eaa4b833ca8cb371829c2129813bd7247065ac58eac42c81e874044e199f48c12aa749a9fe6bb6e4bddc1b72b9ab4579283e62445555d5b2921424213d09a776152361c46988b82be8a7111bc8198f932e379b8f9825f01af0f5e5cacbf8bfe274bf674f6eaa6e338e04259f58d438fd6391e158c991e155966218e6a432703a84068a3254396574985718895f9bae6485ebc32b6eb32f2606164d70c22eb69295caa770dc4df161c12202fc51b5f6b67577223fcb9443b66a5443f1229380ada014b89412c210851241198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa2b451f25ea40ef8a6bbf6685bdeb5c517d892b7df354afc9b115112402fdbcc6110e32080d1871020cacc07adbf2bd1f18335375798e7c65728d81fcad2a3110233f3ddcd7a051aa58d45f1cb43db3e34a73f4e8186f1ec0f683045e23c14fdb2eaa95d1fec9deced40c5be4803c6e81b565eb02efb180d5060981640116af4b2c2460c2348677dc303426ce941fd7370aa9af05e0b6edfd7bcd74615e3a894c0231a91b920126bf0547ac461f04a4d351db35c21d9936a11d53eb53ce4a13d2"_hex,
    "1bce8fa5482d9e50dfea4fb1dd94522e9b716f44d9918d6708fac0f0881938632a4338da2f280b176ab6924abb4775b55b508a8e36fff191023fdc5e99ba928b13bb5bd8d9a2b2822aacf155d7b22beebd4fe1910bd0dbb2834f2dc949f65cf60fc09cf79df13a761e90268de37a3595a7e9dc971fcaf7b26b784559036dfbb00c4f7aaa0d95a7cdeb1854ddef2a87b9393b6ce296e3c0ec20af93a0fde37abb2b8903140adc77bc3ed134c34571e16e949eb7d4a827da48859a9614aba82f722d4d9aa7e302d9df41749d5507949d05dbea33fbb16c643b22f599a2be6df2e214bedd503c37ceb061d8ec60209fe345ce89830a19230301f076caff004d19260967032fcbf776d1afc985f88877f182d38480a653f2decaa9794cbc3bf3060c0e187847ad4c798374d0d6732bf501847dd68bc0e071241e0213bc7fc13db7ab304cfbd1e08a704a99f5e847d93f8c3caafddec46b7a0d379da69a4d112346a71739c1b1a457a8c7313123d24d2f9192f896b7c63eea05a9d57f06547ad0cec829ad8a4a19c8558b7586b3748ef5315ba4520e87bf714177ded2b8b0dee8a03e067cb77535c18066291a1f20a16b7fb8f5d609ad5be42d1598bca446703d74c6198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa2d1b4674ee05363271f65f69fb5aa3d24145eb76f76bf49477e7950b8b4a050c18a6763f1cbe6d2334efcd94661dd802125011c7aba93167d8e25320640621882c4e22719c67bf7bddedcc98face8265be63ccdcef8139c221f21326aa48d1bd0700cbe071c394f095926c90427fe8a412216739e7633acb7c02cd719c12ecb92b34f9525b49f109aed50c68544acf38750b4c7334709d328de3973744953fcb0923b1a411590566dc946db78f12e46e568b91150d4b929ff7b4b5aba0fbab7b"_hex,
};

template <>
const inline std::array inputs<PrecompileId::point_evaluation>{
    // Inputs taken randomly from Mainnet
    // https://etherscan.io/address/0x000000000000000000000000000000000000000a/advanced#internaltx
    "012b08a0504a63aac18383db69fe6b52fc833e3d060b87c2726c4140c909d91807dddd3c80995c2bb3012943e2036e77490b1f6ddc58ca39a4fb4f3225ae56ab11dc2c4d89f777f0f5c2a51f45b73ff1538761f9cf23ed74c74472fea625ad8bace1db77e25ceb316d914182e05dd810f112352e1d6ed9e47af28e2f64e22b94c411794359c2273bc10bc0390963fb1a97bb642307bfa4424c66bd90ecc0ecffd5045e492b40304df20346693db7450457e2c72588a6a2b1a16909e2ab1e6284"_hex,
    "019cd755316533108b9eade41e35a16442ae76acd5b7d4e8903ecb9d9f48348a00000000000000000000000000000000dd372dcb4e5565861fc29cfb12f4373861e6e2dfca75084191a505f7988db8e82a4a4a09734b6fd7677d590a1cb512768c381fc4957f406ef89996d9dfa1d39b5c8d1368569e56fd61036c537400a3f4515eeb0c4d183142daa2c30423e0c3fa84667445c1669d3a3e3fce8a1144811e4452841399318c21cca9d20c91fb162929c4e96d391b70158bcd4c69b682b272"_hex,
    "0187576b6a38dd4ca8ce00e35dd12d1dd91e06ba3bde49d01568103d826d59732fd172adc351401950681fb66f9464410b15437ab00599aede3f90d0d9552bd162920cfc9b91d123f2c24034006fc9b7f5217cfae1022be231b6bd37262fda83ac48e50cbfeeee227daee56a8bff2f96ede7757b6f2598bd40b14d75b04c07a92299443d1eabe857f57fc95b0ca8b121adff55fad542926063245c402008a846c60eeca2e419a3e9e12ddfc0184a606b31d39268d8b580b57ac274501858bdb5"_hex,
    "0145e6c573f2f24f95eeddb687df7da5da51ae1d58bc3691ff52c8d667e704db0000000000000000000000000000000076231706fc7f1f5cd05a88ed538b74ab2672abe246a6042b24c709294ea2e85672a6edc7aee8ab556adfd7af889086afa1bf23edb5e0300f4d924350197c497f084af76365a6209c4b93f00b1ffc803fb7847ca51f4fc1df4fdb9298c16d6a1ea038d42f9ffa40e872eb722e095ea19ff4f2e891a2676b93905476bc8186b741f64c7281f7bba1a14e086316bf5e4b67"_hex,
    "0129c00365c61f29b376a0ff296052604481bce870816c0b1d8a8643d5903c7e000000000000000000000000000000000ae90ade08feef8d4531b692a6ea98ff07cee3b22e47da139784b96a01c6f2291ecd756cd520c10b4c86db65c7ab754a8c4174fa25da26bb3121232ee8ab7d7bdacf4662971bf9fdc92a374b98dc8ca844ae3950ff5bdd1d956b9169666fcaefb44a2aae8ddcbb7be512604565391bc1d5468488c11dcf27be9f2003a651688d660d82060c225c078192ecb8c25ba802"_hex,
    "018490afa27e04a58f6be1ccd8376ad77819954b5c2c950eb88c5e23413e75356056276dbe61c3076bb23c172adb59beb669713669f42036f305d33e39405e4747420b62257ed239139f68d6f70904a3970809e2c159a5d869f2fe3d28f876ef8d6124ae4698b9b10d5333ed73fedde92b76d7009febd0bbd3eef4748bcfbf8080c452fc31461045e03e24d1a4db246a94f75bad459310cec7f3fe8f9798ba615fe3dffba3dd074d4b906e5c0b1a0db916a519f6251ce9b0f327e0628897f271"_hex,
    "01ae47a1b7702fdc67641c971a8a6b3296f9273667ac2fc540934aedd8d7a8ef3e3af8f3f90a55415e6e8b50e2b86b1b227de39feef2b98d840f39774220ca492345c4e5ba1ed2c0e414bd22fc9155c786e667b009272c6ff1596329668288b0abd3f3aff02af02fdff85f322067004c0a44ea8626d033f3c95470bc7fdda33a3f2ecf49ea24b94aba043b295b1ba82d8aa2ad2b1b9b2b0556679828f0e64a27988f1d9ebda3b00b9c6dbdee6e50aafdffd092583aeba3d42eb48d0cb09da2cc"_hex,
    "015234bf406d81ea1d44ef75f19f9932b426fb8c76ffffe93906d6f7dce0d04900000000000000000000000000000000c3e098d7dad534d2d51cd14da7e73cf442f7483e30344d2efe4d2c7ea3d8b67da3131476983d45d625b0ffabe960395489f402c36d9837eb7c0872a223dd64233e5ba7c6a5dd72de7f8c8406f3f87e5e31df83132ef527aa9dfd3a2f56c98799980fd810ab52f4edd43347a64889d2f9850acbe16d9494478c1a462b69a099a960a98f48971d50b7453e2a03227577b1"_hex,
    "01da11f18d57a31a52071af0062552bca6477958994aa068473a7182241ba65c0000000000000000000000000000000061acc5cf049e854931e084b9bc044ecb4bda7c50de18c50ec84b6d13009bb56afa474010fed9a9c861fc76077eb0b327ad2e1b9700e19f435fda3ad6a53d855315cf61ee2cf24d80b9fbf5523ed5ce76a5267617a4b4bd63234d37430ff0274f8024e664b701b13589313f6b315d32122effb0224b223e055c520c3593df101fcb5c51f823d7eb9a2b882e4c9cb46e2b"_hex,
    "01ff83fbe4488061b695d9e4632e9ab23c5b9dfb046241fac921659c2e3b6a4e5e88a0c20ef27ae5dea6e83a748115df152b207362c022a43c8ebbfbec73ea2a2b38376a1de4ed9abd35175ac422af7df2c6ddf1503979964b1d217747c108978969cc0fcbd47dba8b1e3cbba16920f3fc694fadbf203b55aa66aaf138a38ace946a7ccddc20f45d796cd60268df8a2487d06c11cdc50247c580c5dd25f6fb486053b73868038cb92c2ae6d429a7bde850177f31c9fde00ca824c8c59cd4ef49"_hex,
};

template <>
const inline std::array inputs<PrecompileId::p256verify>{
    // Inputs taken from EEST positive test cases.
    "00000000690ed426ccf17803ebe2bd0884bcd58a1bb5e7477ead3645f356e7a916aea964a2f6506d6f78c81c91fc7e8bded7d397738448de1e19a0ec580bf266252cd762130c6667cfe8b7bc47d27d78391e8e80c578d1cd38c3ff033be928e92927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e"_hex,
    "0eaae8641084fa979803efbfb8140732f4cdcf66c3f78a000000003c278a6b215291deaf24659ffbbce6e3c26f6021097a74abdbb69be4fb10419c0c496c946665d6fcf336d27cc7cdb982bb4e4ecef5827f84742f29f10abf83469270a03dc32927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e"_hex,
    "2c3f26f96a3ac0051df4989bffffffff9fd64886c1dc4f9924d8fd6f0edb048481f2359c4faba6b53d3e8c8c3fcc16a948350f7ab3a588b28c17603a431e39a8cd6f6a5cc3b55ead0ff695d06c6860b509e46d99fccefb9f7f9e101857f743002927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e"_hex,
    "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9131230428405560dcb88fb5a646836aea9b23a23dd973dcbe8014c87b8b20eb070f9344d6e812ce166646747694a41b0aaf97374e19f3c5fb8bd7ae3d9bd0beffbcbb2914c79f045eaa6ecbbc612816b3be5d2d6796707d8125e9f851c18af015000000001352bb4a0fa2ea4cceb9ab63dd684ade5a1127bcf300a698a7193bc2"_hex,
    "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f9196843dd03c22abd2f3b782b170239f90f277921becc117d0404a8e4e36230c28f2be378f526f74a543f67165976de9ed9a31214eb4d7e6db19e1ede123dd991d2829c31faa2e400e344ed94bca3fcd0545956ebcfe8ad0f6dfa5ff8effffffffa01aafaf000e52585855afa7676ade284113099052df57e7eb3bd37ebeb9222e"_hex,
    "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25000000000000000000000000000000004319055358e8617b0c46353d039cdaabffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254ed705d16f80987e2d9b1a6957d29ce22febf7d10fa515153182415c8361baaca4b1fc105ee5ce80d514ec1238beae2037a6f83625593620d460819e8682160926"_hex,
    "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e2530e782f964b2e2ff065a051bc7adc20615d8c43a1365713c88268822c253bcce5b16df652aa1ecb2dc8b46c515f9604e2e84cacfa7c6eec30428d2d3f4e08ed504aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d"_hex,
    "532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254e3cd8d2f81d6953b0844c09d7b560d527cd2ef67056893eadafa52c8501387d59ee41fdb4d10402ce7a0c5e3b747adfa3a490b62a6b7719068903485c0bb6dc2d"_hex,
    "bb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca6050237cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc4766997849249248db6db6dbb6db6db6db6db6db5a8b230d0b2b51dcd7ebf0c9fef7c185501421277be45a5eefec6c639930d636032565af420cf3373f557faa7f8a06438673d6cb6076e1cfcdc7dfe7384c8e5cac08d74501f2ae6e89cad195d0aa1371"_hex,
    "dc1921946f4af96a2856e7be399007c9e807bdf4c5332f19f59ec9dd1bb8c7b3530bd6b0c9af2d69ba897f6b5fb59695cfbf33afe66dbadcf5b8d2a2a6538e23d85e489cb7a161fd55ededcedbf4cc0c0987e3e3f0f242cae934c72caa3f43e904aaec73635726f213fb8a9e64da3b8632e41495a944d0045b522eba7240fad587d9315798aaa3a5ba01775787ced05eaaf7b4e09fc81d6d1aa546e8365d525d"_hex,
};

template <PrecompileId Id, ExecuteFn Fn>
void precompile(benchmark::State& state)
{
    int64_t batch_gas_cost = 0;
    size_t max_output_size = 0;
    for (const auto& input : inputs<Id>)
    {
        const auto r = analyze<Id>(input, EVMC_LATEST_STABLE_REVISION);
        batch_gas_cost += r.gas_cost;
        max_output_size = std::max(max_output_size, r.max_output_size);
    }
    const auto output = std::make_unique_for_overwrite<uint8_t[]>(max_output_size);


    int64_t total_gas_used = 0;
    while (state.KeepRunningBatch(inputs<Id>.size()))
    {
        for (const auto& input : inputs<Id>)
        {
            const auto [status, _] = Fn(input.data(), input.size(), output.get(), max_output_size);
            if (status != EVMC_SUCCESS) [[unlikely]]
            {
                state.SkipWithError("invalid result");
                return;
            }
        }
        total_gas_used += batch_gas_cost;
    }

    using benchmark::Counter;
    state.counters["gas_used"] = Counter(static_cast<double>(batch_gas_cost));
    state.counters["gas_rate"] = Counter(static_cast<double>(total_gas_used), Counter::kIsRate);
}

template <ExecuteFn Fn>
void modexp(benchmark::State& state)
{
    const auto base_mod_len = static_cast<size_t>(state.range(0));
    const auto exp_bits = static_cast<size_t>(state.range(1));
    const auto exp_len = (exp_bits + 7) / 8;
    const auto exp_clz = exp_bits % 8 == 0 ? 0 : 8 - exp_bits % 8;

    const auto payload_len = 2 * base_mod_len + exp_len - 1;
    const auto input_len = 3 * 32 + payload_len;
    const auto input = std::make_unique_for_overwrite<uint8_t[]>(input_len);
    intx::be::unsafe::store(&input[0], intx::uint256{base_mod_len});
    intx::be::unsafe::store(&input[32], intx::uint256{exp_len});
    intx::be::unsafe::store(&input[64], intx::uint256{base_mod_len});
    const std::span payload{&input[3 * 32], payload_len};
    std::fill_n(&payload[0], base_mod_len, 0xff);
    std::fill_n(&payload[base_mod_len + 1], exp_len - 1, 0xff);
    payload[base_mod_len] = 0xff >> exp_clz;
    // Skip the last byte in the mod to make input incomplete and mod even.
    std::fill_n(&payload[base_mod_len + exp_len], base_mod_len - 1, 0xff);

    const auto output = std::make_unique_for_overwrite<uint8_t[]>(base_mod_len);

    const auto gas_cost = expmod_analyze({input.get(), input_len}, EVMC_PRAGUE).gas_cost;
    int64_t total_gas_used = 0;
    for ([[maybe_unused]] auto _ : state)
    {
        auto r = Fn(input.get(), input_len, output.get(), base_mod_len);
        benchmark::DoNotOptimize(r);
        total_gas_used += gas_cost;
    }

    using benchmark::Counter;
    state.counters["gas_used"] = Counter(static_cast<double>(gas_cost));
    state.counters["gas_rate"] = Counter(static_cast<double>(total_gas_used), Counter::kIsRate);
}
#define MODEXP_ARGS                     \
    ->ArgNames({"mod_len", "exp_bits"}) \
        ->Args({1 * 8, 604})            \
        ->Args({2 * 8, 152})            \
        ->Args({3 * 8, 68})             \
        ->Args({4 * 8, 39})             \
        ->Args({5 * 8, 25})             \
        ->Args({6 * 8, 18})             \
        ->Args({7 * 8, 13})             \
        ->Args({8 * 8, 10})             \
        ->Args({9 * 8, 8})              \
        ->Args({10 * 8, 7})             \
        ->Args({11 * 8, 6})             \
        ->Args({12 * 8, 5})             \
        ->Args({14 * 8, 4})             \
        ->Args({17 * 8, 3})             \
        ->Args({24 * 8, 2})             \
        ->Args({25 * 8, 1})             \
        ->Args({32 * 8, 2})             \
        ->Args({33 * 8, 2})             \
        ->Args({63 * 8, 2})             \
        ->Args({64 * 8, 2})             \
        ->Args({65 * 8, 2})             \
        ->Args({127 * 8, 2})            \
        ->Args({128 * 8, 2})
BENCHMARK(modexp<expmod_execute>) MODEXP_ARGS;
#ifdef EVMONE_PRECOMPILES_GMP
BENCHMARK(modexp<expmod_execute_gmp>) MODEXP_ARGS;
#endif
#undef MODEXP_ARGS

BENCHMARK_TEMPLATE(precompile, PrecompileId::identity, identity_execute);

namespace bench_ecrecovery
{
constexpr auto evmmax_cpp = ecrecover_execute;
BENCHMARK_TEMPLATE(precompile, PrecompileId::ecrecover, evmmax_cpp);
#ifdef EVMONE_PRECOMPILES_SILKPRE
constexpr auto libsecp256k1 = silkpre_ecrecover_execute;
BENCHMARK_TEMPLATE(precompile, PrecompileId::ecrecover, libsecp256k1);
#endif
}  // namespace bench_ecrecovery

namespace bench_expmod
{
constexpr auto evmone = expmod_execute;
BENCHMARK(precompile<PrecompileId::expmod, evmone>);
#ifdef EVMONE_PRECOMPILES_GMP
constexpr auto gmp = expmod_execute_gmp;
BENCHMARK(precompile<PrecompileId::expmod, gmp>);
#endif
#ifdef EVMONE_PRECOMPILES_SILKPRE
constexpr auto silkpre = silkpre_expmod_execute;
BENCHMARK(precompile<PrecompileId::expmod, silkpre>);
#endif
}  // namespace bench_expmod

namespace bench_ecadd
{
constexpr auto evmmax_cpp = ecadd_execute;
BENCHMARK_TEMPLATE(precompile, PrecompileId::ecadd, evmmax_cpp);
#ifdef EVMONE_PRECOMPILES_SILKPRE
constexpr auto libff = silkpre_ecadd_execute;
BENCHMARK_TEMPLATE(precompile, PrecompileId::ecadd, libff);
#endif
}  // namespace bench_ecadd

namespace bench_ecmul
{
constexpr auto evmmax_cpp = ecmul_execute;
BENCHMARK_TEMPLATE(precompile, PrecompileId::ecmul, evmmax_cpp);
#ifdef EVMONE_PRECOMPILES_SILKPRE
constexpr auto libff = silkpre_ecmul_execute;
BENCHMARK_TEMPLATE(precompile, PrecompileId::ecmul, libff);
#endif
}  // namespace bench_ecmul

namespace bench_ecpairing
{
constexpr auto evmmax_cpp = ecpairing_execute;
BENCHMARK_TEMPLATE(precompile, PrecompileId::ecpairing, evmmax_cpp);
#ifdef EVMONE_PRECOMPILES_SILKPRE
constexpr auto libff = silkpre_ecpairing_execute;
BENCHMARK_TEMPLATE(precompile, PrecompileId::ecpairing, libff);
#endif
}  // namespace bench_ecpairing

namespace bench_kzg
{
constexpr auto evmone_blst = point_evaluation_execute;
BENCHMARK_TEMPLATE(precompile, PrecompileId::point_evaluation, evmone_blst);
}  // namespace bench_kzg

}  // namespace

namespace bench_p256verify
{
constexpr auto evmone_cpp = p256verify_execute;
BENCHMARK_TEMPLATE(precompile, PrecompileId::p256verify, evmone_cpp);
}  // namespace bench_p256verify

BENCHMARK_MAIN();
